package com.dd.cloud.user.service.phar.pharservice;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.dd.cloud.common.constants.PharConstants;
import com.dd.cloud.common.constants.PresConstants;
import com.dd.cloud.common.enums.ZkExceptionEnum;
import com.dd.cloud.common.exception.ZekeException;
import com.dd.cloud.common.interceptor.UserInterceptor;
import com.dd.cloud.common.utils.AESUtil;
import com.dd.cloud.common.utils.AreaCodeUtil;
import com.dd.cloud.common.utils.CalendarUtil;
import com.dd.cloud.common.vo.LoginInfo;
import com.dd.cloud.user.DTO.CallbackPresStatusReq;
import com.dd.cloud.user.DTO.CancelPresReq;
import com.dd.cloud.user.DTO.CommonParamReq;
import com.dd.cloud.user.DTO.yf.*;
import com.dd.cloud.user.entity.doctor.PatientMedCard;
import com.dd.cloud.user.entity.order.OrderPay;
import com.dd.cloud.user.entity.phar.Pharmacy;
import com.dd.cloud.user.entity.phar.PharmacyDocking;
import com.dd.cloud.user.entity.pres.PresHandleRecord;
import com.dd.cloud.user.entity.pres.PresPrescription;
import com.dd.cloud.user.entity.pres.PresPretrialDrugs;
import com.dd.cloud.user.entity.pres.PresYfDetail;
import com.dd.cloud.user.req.pres.PresCreateReq;
import com.dd.cloud.user.req.pres.PresCreateYfReq;
import com.dd.cloud.user.req.pres.PresPatientAddrReq;
import com.dd.cloud.user.service.doctor.IDoctorEquityService;
import com.dd.cloud.user.service.log.ILogErrorService;
import com.dd.cloud.user.service.order.IOrderPayService;
import com.dd.cloud.user.service.phar.IPharmacyDockingService;
import com.dd.cloud.user.service.phar.IPharmacyService;
import com.dd.cloud.user.service.pres.*;
import com.dd.cloud.user.service.sms.ISmsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author Lx
 * @version 1.0
 */
@Slf4j
@Service
public class YfPharService extends PharAbstractService {
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private ILogErrorService logErrorService;
    @Autowired
    private IPharmacyService pharmacyService;
    @Autowired
    private IDrugsModelService drugsModelService;
    @Autowired
    private IPresYfDetailService presYfDetailService;
    @Autowired
    private IPharmacyDockingService pharmacyDockingService;
    @Autowired
    private IOrderPayService orderPayService;
    @Autowired
    private IPresPrescriptionService presPrescriptionService;
    @Autowired
    private IPresHandleRecordService presHandleRecordService;
    @Autowired
    private IPresPretrialDrugsService presPretrialDrugsService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private ISmsService smsService;
    private final String tokenRedisKey = "yf_token_key";
    private final String targetDataSourceRedisKey = "yf_targetDataSource_key";

    @Autowired
    private IDoctorEquityService doctorEquityService;

    /**
     * 获取一方制药targetDataSource
     *
     * @return
     */
    public String getTargetDataSource() {
        String value = redisTemplate.opsForValue().get(targetDataSourceRedisKey);
        if (!StringUtils.isBlank(value)) {
            return value;
        }
        QueryWrapper<Pharmacy> qp = new QueryWrapper<>();
        qp.lambda().eq(Pharmacy::getFlag, PharConstants.Flag.YF);
        Pharmacy pharmacy = pharmacyService.getOne(qp);
        if (pharmacy == null) {
            logErrorService.presBackLog("药房不存在", "获取一方制药targetDataSource数据", "pharFlag=" + PharConstants.Flag.YF);
            return "";
        }
        QueryWrapper<PharmacyDocking> qd = new QueryWrapper<>();
        qd.lambda().eq(PharmacyDocking::getPharId, pharmacy.getId()).eq(PharmacyDocking::getStatus, PharConstants.DockingStatus.NOMER);
        PharmacyDocking pharmacyDocking = pharmacyDockingService.getOne(qd);
        if (pharmacyDocking == null) {
            logErrorService.presBackLog("药房接口信息不存在", "获取一方制药targetDataSource数据", "pharId=" + pharmacy.getId());
            return "";
        }
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("Content-Type", "application/json");
        HttpEntity<String> entity = new HttpEntity<>("{\"loginModel\":\"secretKey\",\"username\":\"" + pharmacyDocking.getEncryptyKey() + "\"}", httpHeaders);
        log.info("请求数据:{}", entity);
        ResponseEntity<String> res;
        try {
            res = restTemplate.postForEntity(pharmacyDocking.getGetTargetDataSourceUrl(), entity, String.class);
        } catch (RestClientException e) {
            e.printStackTrace();
            logErrorService.presBackLog("药房获取targetDataSource信息接口错误信息", "获取一方制药targetDataSource数据", "message=" + e.getMessage());
            return "";
        }
        log.info("result:{}", res.getBody());
        JSONObject jsonObj = JSON.parseObject(res.getBody());
        if (jsonObj == null) {
            logErrorService.presBackLog("药房获取targetDataSource信息接口无数据返回", "获取一方制药targetDataSource数据", "res=" + res);
            return "";
        }
        if (jsonObj.getInteger("code") != 200) {
            logErrorService.presBackLog("药房获取targetDataSource信息接口返回异常信息", "获取一方制药targetDataSource数据", "res=" + res);
            return "";
        }
        String token = jsonObj.getJSONArray("data").getJSONObject(0).getString("databaseCode");
        redisTemplate.opsForValue().set(targetDataSourceRedisKey, token, 24L, TimeUnit.HOURS);
        return token;
    }

    /**
     * 获取一方制药token
     *
     * @return
     */
    public String getToken() {
        String value = redisTemplate.opsForValue().get(tokenRedisKey);
        if (!StringUtils.isBlank(value)) {
            return value;
        }
        QueryWrapper<Pharmacy> qp = new QueryWrapper<>();
        qp.lambda().eq(Pharmacy::getFlag, PharConstants.Flag.YF);
        Pharmacy pharmacy = pharmacyService.getOne(qp);
        if (pharmacy == null) {
            logErrorService.presBackLog("药房不存在", "获取一方制药token数据", "pharFlag=" + PharConstants.Flag.YF);
            return "";
        }
        QueryWrapper<PharmacyDocking> qd = new QueryWrapper<>();
        qd.lambda().eq(PharmacyDocking::getPharId, pharmacy.getId()).eq(PharmacyDocking::getStatus, PharConstants.DockingStatus.NOMER);
        PharmacyDocking pharmacyDocking = pharmacyDockingService.getOne(qd);
        if (pharmacyDocking == null) {
            logErrorService.presBackLog("药房接口信息不存在", "获取一方制药token数据", "pharId=" + pharmacy.getId());
            return "";
        }
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("Content-Type", "application/json");
        httpHeaders.add("target-data-source", getTargetDataSource());
        HttpEntity<String> entity = new HttpEntity<>("{\"organizationSecretKey\":\"" + pharmacyDocking.getEncryptyKey() + "\"}", httpHeaders);
        log.info("请求数据:{}", entity);
        ResponseEntity<String> res;
        try {
            res = restTemplate.postForEntity(pharmacyDocking.getGetTokenUrl(), entity, String.class);
        } catch (RestClientException e) {
            e.printStackTrace();
            logErrorService.presBackLog("药房获取token信息接口错误信息", "获取一方制药token数据", "message=" + e.getMessage());
            return "";
        }
        log.info("result:{}", res.getBody());
        JSONObject jsonObj = JSON.parseObject(res.getBody());
        if (jsonObj == null) {
            logErrorService.presBackLog("药房获取token信息接口无数据返回", "获取一方制药token数据", "res=" + res);
            return "";
        }
        if (jsonObj.getInteger("code") != 200) {
            logErrorService.presBackLog("药房获取token信息接口返回异常信息", "获取一方制药token数据", "res=" + res);
            return "";
        }
        String token = jsonObj.getJSONObject("data").getString("token");
        redisTemplate.opsForValue().set(tokenRedisKey, token, 2L, TimeUnit.HOURS);
        return token;
    }

    /**
     * 同步一方制药颗粒药材数
     */
    public void syncYfKlDrug() {
        QueryWrapper<Pharmacy> qp = new QueryWrapper<>();
        qp.lambda().eq(Pharmacy::getFlag, PharConstants.Flag.YF);
        Pharmacy pharmacy = pharmacyService.getOne(qp);
        if (pharmacy == null) {
            logErrorService.presBackLog("药房不存在", "获取一方制药颗粒药材数据", "pharFlag=" + PharConstants.Flag.YF);
            return;
        }
        QueryWrapper<PharmacyDocking> qd = new QueryWrapper<>();
        qd.lambda().eq(PharmacyDocking::getPharId, pharmacy.getId()).eq(PharmacyDocking::getStatus, PharConstants.DockingStatus.NOMER);
        PharmacyDocking pharmacyDocking = pharmacyDockingService.getOne(qd);
        if (pharmacyDocking == null) {
            logErrorService.presBackLog("药房接口信息不存在", "获取一方制药颗粒药材数据", "pharId=" + pharmacy.getId());
            return;
        }
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("Content-Type", "application/json");
        httpHeaders.add("target-data-source", getTargetDataSource());
        httpHeaders.add("xmtoken", getToken());
        SendQueryDrugKlDTO query = new SendQueryDrugKlDTO();
        query.setHostpitalId(pharmacyDocking.getMchId());
        query.setSecretKey(pharmacyDocking.getSecretKey());
        HttpEntity<String> entity = new HttpEntity<>(JSON.toJSONString(query), httpHeaders);
        log.info("请求数据:{}", entity);
        ResponseEntity<String> res;
        try {
            res = restTemplate.postForEntity(pharmacyDocking.getGetKlDrugUrl(), entity, String.class);
        } catch (RestClientException e) {
            e.printStackTrace();
            logErrorService.presBackLog("药房获取颗粒药材信息接口错误信息", "获取一方制药颗粒药材数据", "message=" + e.getMessage());
            return;
        }
        log.info("result:{}", res.getBody());
        JSONObject jsonObj = JSON.parseObject(res.getBody());
        if (jsonObj == null) {
            logErrorService.presBackLog("药房获取颗粒药材信息接口无数据返回", "获取一方制药颗粒药材数据", "res=" + res);
            return;
        }
        if (jsonObj.getInteger("code") != 200) {
            logErrorService.presBackLog("药房获取颗粒药材信息接口返回异常信息", "获取一方制药颗粒药材数据", "res=" + res);
            return;
        }
        List<ReturnQueryDrugKlResultDTO> resultDTOList = JSON.parseArray(jsonObj.getString("data"), ReturnQueryDrugKlResultDTO.class);
        drugsModelService.syncYfKlDrugInfo(resultDTOList, pharmacy.getId());
    }

    /**
     * 检查一方制药颗粒药材超量/配伍禁忌
     *
     * @param send
     * @return
     */
    public Map<?, ?> checkDrugKlExcess(SendCheckDrugKlExcessDTO send) {
        QueryWrapper<Pharmacy> qp = new QueryWrapper<>();
        qp.lambda().eq(Pharmacy::getFlag, PharConstants.Flag.YF);
        Pharmacy pharmacy = pharmacyService.getOne(qp);
        if (pharmacy == null) {
            logErrorService.presBackLog("药房不存在", "检查一方制药颗粒药材超量/配伍禁忌", "pharFlag=" + PharConstants.Flag.YF);
            return new HashMap<>();
        }
        QueryWrapper<PharmacyDocking> qd = new QueryWrapper<>();
        qd.lambda().eq(PharmacyDocking::getPharId, pharmacy.getId()).eq(PharmacyDocking::getStatus, PharConstants.DockingStatus.NOMER);
        PharmacyDocking pharmacyDocking = pharmacyDockingService.getOne(qd);
        if (pharmacyDocking == null) {
            logErrorService.presBackLog("药房接口信息不存在", "检查一方制药颗粒药材超量/配伍禁忌", "pharId=" + pharmacy.getId());
            return new HashMap<>();

        }
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("Content-Type", "application/json");
        httpHeaders.add("target-data-source", getTargetDataSource());
        httpHeaders.add("xmtoken", getToken());
        HttpEntity<String> entity = new HttpEntity<>(JSON.toJSONString(send), httpHeaders);
        log.info("请求数据:{}", entity);
        ResponseEntity<String> res;
        try {
            res = restTemplate.postForEntity(pharmacyDocking.getCheckKlDrugExcessUrl(), entity, String.class);
        } catch (RestClientException e) {
            e.printStackTrace();
            logErrorService.presBackLog("药房检查颗粒药材超量/配伍禁忌接口错误信息", "检查一方制药颗粒药材超量/配伍禁忌", "message=" + e.getMessage());
            return new HashMap<>();
        }
        log.info("result:{}", res.getBody());
        JSONObject jsonObj = JSON.parseObject(res.getBody());
        if (jsonObj == null) {
            logErrorService.presBackLog("药房检查颗粒药材超量/配伍禁忌接口无数据返回", "检查一方制药颗粒药材超量/配伍禁忌", "res=" + res);
            return new HashMap<>();
        }
        if (jsonObj.getInteger("code") != 200) {
            logErrorService.presBackLog("药房检查颗粒药材超量/配伍禁忌接口返回异常信息", "检查一方制药颗粒药材超量/配伍禁忌", "res=" + res);
            return new HashMap<>();
        }
        try {
            return JSON.parseObject(jsonObj.getString("data"), Map.class);
        } catch (Exception e) {
            logErrorService.presBackLog("药房获检查颗粒药材超量/配伍禁忌接口数据转换异常", "检查一方制药颗粒药材超量/配伍禁忌", "res=" + res);
            return new HashMap<>();
        }
    }

    /**
     * 检查一方制药颗粒药材库存
     *
     * @param send
     * @return
     */
    public ReturnCheckDrugKlStockResultDTO checkDrugKlStock(SendCheckDrugKlStockDTO send) {
        ReturnCheckDrugKlStockResultDTO dto = new ReturnCheckDrugKlStockResultDTO();
        QueryWrapper<Pharmacy> qp = new QueryWrapper<>();
        qp.lambda().eq(Pharmacy::getFlag, PharConstants.Flag.YF);
        Pharmacy pharmacy = pharmacyService.getOne(qp);
        if (pharmacy == null) {
            logErrorService.presBackLog("药房不存在", "检查一方制药颗粒药材库存", "pharFlag=" + PharConstants.Flag.YF);
            return dto;
        }
        QueryWrapper<PharmacyDocking> qd = new QueryWrapper<>();
        qd.lambda().eq(PharmacyDocking::getPharId, pharmacy.getId()).eq(PharmacyDocking::getStatus, PharConstants.DockingStatus.NOMER);
        PharmacyDocking pharmacyDocking = pharmacyDockingService.getOne(qd);
        if (pharmacyDocking == null) {
            logErrorService.presBackLog("药房接口信息不存在", "检查一方制药颗粒药材库存", "pharId=" + pharmacy.getId());
            return dto;
        }
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("Content-Type", "application/json");
        httpHeaders.add("target-data-source", getTargetDataSource());
        httpHeaders.add("xmtoken", getToken());
        send.setHostpitalId(pharmacyDocking.getMchId());
        send.setSecretKey(pharmacyDocking.getSecretKey());
        HttpEntity<String> entity = new HttpEntity<>(JSON.toJSONString(send), httpHeaders);
        log.info("请求数据:{}", entity);
        ResponseEntity<String> res;
        try {
            res = restTemplate.postForEntity(pharmacyDocking.getCheckKlDrugStockUrl(), entity, String.class);
        } catch (RestClientException e) {
            e.printStackTrace();
            logErrorService.presBackLog("药房检查颗粒药材库存接口错误信息", "检查一方制药颗粒药材库存", "message=" + e.getMessage());
            return dto;
        }
        log.info("result:{}", res.getBody());
        JSONObject jsonObj = JSON.parseObject(res.getBody());
        if (jsonObj == null) {
            logErrorService.presBackLog("药房检查颗粒药材库存接口无数据返回", "检查一方制药颗粒药材库存", "res=" + res);
            return dto;
        }
        if (jsonObj.getInteger("code") != 200) {
            logErrorService.presBackLog("药房检查颗粒药材库存接口返回异常信息", "检查一方制药颗粒药材库存", "res=" + res);
            return dto;
        }
        try {
            dto = JSON.parseObject(jsonObj.getString("data"), ReturnCheckDrugKlStockResultDTO.class);
            try {
                dto.setContentString(dto.getContentString().replace("(国)", ",").replace("(企)", ","));
            } catch (Exception e) {
                logErrorService.presBackLog("药房获检查颗粒药材库存接口数据处理异常", "检查一方制药颗粒药材库存", "res=" + res);
                return dto;
            }
        } catch (Exception e) {
            logErrorService.presBackLog("药房获检查颗粒药材库存接口数据转换异常", "检查一方制药颗粒药材库存", "res=" + res);
            return dto;
        }
        return dto;
    }

    /**
     * 处理一方制药状态流转
     */
    public void presStatusRoamYf() {
        List<String> thirdIds = presYfDetailService.queryPresStatusRoamThirdPartyIdListYf();
        QueryWrapper<Pharmacy> qp = new QueryWrapper<>();
        qp.lambda().eq(Pharmacy::getFlag, PharConstants.Flag.YF);
        Pharmacy pharmacy = pharmacyService.getOne(qp);
        if (pharmacy == null) {
            logErrorService.presBackLog("药房不存在", "处理一方制药状态流转", "pharFlag=" + PharConstants.Flag.YF);
            return;
        }
        QueryWrapper<PharmacyDocking> qd = new QueryWrapper<>();
        qd.lambda().eq(PharmacyDocking::getPharId, pharmacy.getId()).eq(PharmacyDocking::getStatus, PharConstants.DockingStatus.NOMER);
        PharmacyDocking pharmacyDocking = pharmacyDockingService.getOne(qd);
        if (pharmacyDocking == null) {
            logErrorService.presBackLog("药房接口信息不存在", "处理一方制药状态流转", "pharId=" + pharmacy.getId());
            return;
        }
        List<PresPrescription> updateListById = new ArrayList<>(thirdIds.size());
        List<PresHandleRecord> saveList = new ArrayList<>(thirdIds.size());
        for (String item : thirdIds) {
            if (item == null) {
                continue;
            }
            String[] splits = item.split(",");
            int status;
            try {
                status = Integer.parseInt(splits[2]);
            } catch (NumberFormatException e) {
                logErrorService.presBackLog("String转Integer错误", "处理一方制药状态流转", "res=" + Arrays.toString(splits));
                continue;
            }
            HttpHeaders httpHeaders = new HttpHeaders();
            httpHeaders.add("Content-Type", "application/json");
            httpHeaders.add("target-data-source", getTargetDataSource());
            httpHeaders.add("xmtoken", getToken());
            SendQueryPresStatusDTO send = new SendQueryPresStatusDTO();
            send.setThirdPartyId(splits[0]);
            HttpEntity<String> entity = new HttpEntity<>(JSON.toJSONString(send), httpHeaders);
            log.info("请求数据:{}", entity);
            ResponseEntity<String> res;
            try {
                res = restTemplate.postForEntity(pharmacyDocking.getPresCallbackUrl(), entity, String.class);
            } catch (RestClientException e) {
                e.printStackTrace();
                logErrorService.presBackLog("药房查询处方状态流转接口错误信息", "处理一方制药状态流转", "message=" + e.getMessage());
                continue;
            }
            log.info("result:{}", res.getBody());
            JSONObject jsonObj = JSON.parseObject(res.getBody());
            if (jsonObj == null) {
                logErrorService.presBackLog("药房查询处方状态流转接无数据返回", "处理一方制药状态流转", "res=" + res);
                continue;
            }
            if (jsonObj.getInteger("code") != 200) {
                logErrorService.presBackLog("药房查询处方状态流转接返回异常信息", "处理一方制药状态流转", "res=" + res);
                continue;
            }
            ReturnQueryPresStatusResultDTO dto;
            try {
                dto = JSON.parseObject(jsonObj.getString("data"), ReturnQueryPresStatusResultDTO.class);
            } catch (Exception e) {
                logErrorService.presBackLog("药房查询处方状态流转接数据转换异常", "处理一方制药状态流转", "res=" + res);
                continue;
            }
            PresPrescription update = new PresPrescription();
            switch (dto.getOrderStatus()) {
                case "1":
                    if (status != PresConstants.PresStatus.AUDITNO) {
                        update.setStatus(PresConstants.PresStatus.AUDITNO);
                    }
                    break;
                case "2":
                    if (status != PresConstants.PresStatus.AUDIT) {
                        update.setStatus(PresConstants.PresStatus.AUDIT);
                    }
                    break;
                case "3":
                    if (status != PresConstants.PresStatus.ADJUST) {
                        update.setStatus(PresConstants.PresStatus.ADJUST);
                    }
                    break;
                case "66":
                    if (status != PresConstants.PresStatus.REVIEW) {
                        update.setStatus(PresConstants.PresStatus.REVIEW);
                    }
                    break;
                case "4":
                    if (status != PresConstants.PresStatus.PACK) {
                        update.setStatus(PresConstants.PresStatus.PACK);
                    }
                    break;
                case "5":
                    if (status != PresConstants.PresStatus.DELIVERY) {
                        update.setStatus(PresConstants.PresStatus.DELIVERY);
                        update.setExpressno(dto.getExpressNo());
                        update.setExpresscompany(dto.getExpressName());
                        PresPrescription presPrescription = presPrescriptionService.getById(splits[1]);
                        smsService.sendDeliveryPres(presPrescription.getTencode(), presPrescription.getDoctorId(), presPrescription.getName(), dto.getExpressNo(), dto.getExpressName());
                        LambdaQueryWrapper<OrderPay> queryWrapper = new LambdaQueryWrapper<>();
                        queryWrapper.eq(OrderPay::getServerNo, presPrescription.getTencode()).eq(OrderPay::getStatus, 2);
                        OrderPay orderPay = orderPayService.getOne(queryWrapper);
                        if (orderPay != null) {
                            doctorEquityService.saveDoctorEquity(orderPay, 2);
                        }
                    }
                    break;
                case "6":
                    if (status != PresConstants.PresStatus.SUC) {
                        update.setStatus(PresConstants.PresStatus.SUC);
                    }
                    break;
                case "8":
                case "9":
                    if (status != PresConstants.PresStatus.CANCEL) {
                        update.setStatus(PresConstants.PresStatus.CANCEL);
                    }
                    break;
                case "7":
                case "10":
                case "11":
                    if (status != PresConstants.PresStatus.ERROR) {
                        update.setStatus(PresConstants.PresStatus.ERROR);
                    }
                    break;
                default:
            }
            if (update.getStatus() != null) {
                update.setTencode(splits[1]);
                update.setUpdateDate(LocalDateTime.now());
                updateListById.add(update);
                PresHandleRecord record = new PresHandleRecord();
                record.setTencode(splits[1]);
                record.setStatus(update.getStatus());
                record.setExpressno(dto.getExpressNo());
                record.setExpresscompany(dto.getExpressName());
                record.setCreateId(-1);
                record.setCreateType(-1);
                record.setCreateDate(LocalDateTime.now());
                saveList.add(record);
            }
        }
        presPrescriptionService.updateBatchById(updateListById);
        presHandleRecordService.saveBatch(saveList);
    }

    @Override
    public void addPresDetail(PresCreateReq req, PatientMedCard medCard) {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo(LoginInfo.UserType.DOCTOR).get();
        PresCreateYfReq yfReq = (PresCreateYfReq) req;
        PresYfDetail detail = new PresYfDetail();
        BeanUtils.copyProperties(yfReq, detail);
        detail.setAddress(yfReq.getAddr());
        detail.setDoctorName(loginInfo.getName());
        detail.setDepartmentName(StringUtils.isBlank(req.getDepName()) ? "中医科" : req.getDepName());
        detail.setClinicalDiagnosis(req.getDisease());
        detail.setPrescriptionName(req.getDisease());
        detail.setSex("男".equals(medCard.getSex()) ? "1" : "2");
        detail.setAge(CalendarUtil.getAge(medCard.getBirthDate()).toString());
        detail.setUserName(medCard.getName());
        detail.setUserPhone(medCard.getMobileNumber());
        detail.setProvince(AreaCodeUtil.getInstance().getProvinceCityDistrictCode(detail.getCity().replace(",", "")));
        detail.setBorrowerProvince(AreaCodeUtil.getInstance().getProvinceCityDistrictCode(detail.getBorrowerCity().replace(",", "")));
        detail.setDrugNum(req.getAllDose().toString());
        detail.setFrequency("每日" + req.getDayDose() + "剂,每天" + req.getDoseNum() + "次,每次1袋");
        detail.setTencode(yfReq.getTencode());
        presYfDetailService.save(detail);
    }

    @Override
    public boolean sendPresToPhar(OrderPay pay) {
        boolean succ = false;
        log.info("发送处方到一方制药药房");
        if (StringUtils.isBlank(pay.getServerNo())) {
            //没有处方编码 数据异常, 退款
            orderPayService.refund(pay.getOrderNo(), 0);
            logErrorService.presBackLog("没有处方编码-数据异常, 退款", "处方发送到一方制药药房异常", "tencode=" + pay.getServerNo());
            return succ;
        }
        PresPrescription presPrescription = presPrescriptionService.getById(pay.getServerNo());
        if (presPrescription == null) {
            //处方为空, 数据异常, 退款
            logErrorService.presBackLog("处方为空-数据异常", "处方发送到一方制药药房异常", "tencode=" + pay.getServerNo());
            return succ;
        }
        if (presPrescription.getStatus() == PresConstants.PresStatus.SENDPHARM) {
            //处方已发送到药房, 此为重复回调
            log.info("处方已发送到药房, 此为重复回调");
            return succ;
        }
        PresYfDetail yfDetail = presYfDetailService.getById(pay.getServerNo());
        if (yfDetail == null) {
            presPrescription.setStatus(PresConstants.PresStatus.SENDPHARMERROR);
            presPrescriptionService.updateById(presPrescription);
            logErrorService.presBackLog("获取发送给药房的详细数据失败", "处方发送到一方制药药房异常", "tencode=" + pay.getServerNo());
            return succ;
        }
        yfDetail.setThirdPartyId(pay.getOrderNo());
        Pharmacy pharmacy = pharmacyService.getById(presPrescription.getPharmId());
        if (pharmacy == null) {
            //药房为空, 数据异常 ,退款
            presPrescription.setStatus(PresConstants.PresStatus.SENDPHARMERROR);
            presPrescriptionService.updateById(presPrescription);
            logErrorService.presBackLog("药房为空-数据异常", "处方发送到一方制药药房异常", "tencode=" + pay.getServerNo());
            return succ;
        }
        QueryWrapper<PharmacyDocking> qd = new QueryWrapper<>();
        qd.lambda().eq(PharmacyDocking::getPharId, pharmacy.getId()).eq(PharmacyDocking::getStatus, PharConstants.DockingStatus.NOMER);
        PharmacyDocking pharmacyDocking = pharmacyDockingService.getOne(qd);
        if (pharmacyDocking == null) {
            //药房为空, 数据异常 ,退款
            presPrescription.setStatus(PresConstants.PresStatus.SENDPHARMERROR);
            presPrescriptionService.updateById(presPrescription);
            logErrorService.presBackLog("药房对接信息为空-数据异常", "处方发送到一方制药药房异常", "pharId=" + pharmacy.getId());
            return succ;
        }
        SendPresBodyDTO bodyDTO = new SendPresBodyDTO();
        BeanUtils.copyProperties(yfDetail, bodyDTO);
        bodyDTO.setThirdPartyId(pay.getOrderNo());
        bodyDTO.setHostpitalId(pharmacyDocking.getMchId());
        bodyDTO.setHostpitalType("3");
        List<SendPresKlDrugsDTO> drugsDTOS = new ArrayList<>();
        QueryWrapper<PresPretrialDrugs> qw = new QueryWrapper<>();
        qw.lambda().eq(PresPretrialDrugs::getTencode, presPrescription.getTencode()).eq(PresPretrialDrugs::getStatus, PresConstants.PresDrugsStatus.NOMER);
        List<PresPretrialDrugs> drugsList = presPretrialDrugsService.list(qw);
        if (drugsList == null || drugsList.isEmpty()) {
            presPrescription.setStatus(PresConstants.PresStatus.SENDPHARMERROR);
            presPrescriptionService.updateById(presPrescription);
            logErrorService.presBackLog("没有处方药品-数据异常", "处方发送到一方制药药房异常", "tencode=" + pay.getServerNo());
            return succ;
        }
        for (PresPretrialDrugs drugs : drugsList) {
            SendPresKlDrugsDTO drugsDTO = new SendPresKlDrugsDTO();
            drugsDTO.setId(drugs.getDrugnum());
            drugsDTO.setLable(drugs.getHerbName());
            drugsDTO.setDrugNum(BigDecimal.valueOf(drugs.getDrugallnum()).toString());
            drugsDTO.setType(drugs.getKlType());
            drugsDTOS.add(drugsDTO);
        }
        String drugsJson = JSON.toJSONString(drugsDTOS);
        SendCheckDrugKlStockDTO check = new SendCheckDrugKlStockDTO();
        check.setDrugNum(yfDetail.getDrugNum());
        check.setFContent(drugsJson);
        check.setPrescriptionContent(drugsJson);
        ReturnCheckDrugKlStockResultDTO checkResult = checkDrugKlStock(check);
        if (checkResult.getStock().equals(1)) {
            presPrescription.setStatus(PresConstants.PresStatus.SENDPHARMERROR);
            presPrescriptionService.updateById(presPrescription);
            logErrorService.presBackLog("一方制药处方药品没有库存", "处方发送到一方制药药房异常", "checkResult=" + checkResult);
            return succ;
        }
        log.info("一方制药下单库存检查 res:{}", checkResult);
        Map<String, ReturnCheckDrugKlStockResultDTO.PrescriptionContent> map = checkResult.getPrescriptionContent().stream().collect(Collectors.toMap(t -> t.getId().toString(), t -> t, (t1, t2) -> t1));
        for (SendPresKlDrugsDTO drugsDTO : drugsDTOS) {
            ReturnCheckDrugKlStockResultDTO.PrescriptionContent content = map.get(drugsDTO.getId());
            if (content != null) {
                drugsDTO.setGranuleNum(content.getGranuleNum());
                drugsDTO.setProportionNum(content.getProportionNum());
            }
        }
        drugsJson = JSON.toJSONString(drugsDTOS);
        bodyDTO.setPrescription_content(drugsJson);
        bodyDTO.setPrescriptionUrl("[\"" + (presPrescription.getPdfUrl() == null ? "" : presPrescription.getPdfUrl()) + "\"]");
        bodyDTO.setClinical_diagnosis(yfDetail.getClinicalDiagnosis());
        bodyDTO.setDepartment_name(yfDetail.getDepartmentName());
        bodyDTO.setDoctor_name(yfDetail.getDoctorName());
        String json = JSON.toJSONString(bodyDTO);
        log.info("json:{}", json);
        try {
            bodyDTO.setEncryptedContent(AESUtil.encrypt(json, pharmacyDocking.getSecretKey()));
        } catch (Exception e) {
            presPrescription.setStatus(PresConstants.PresStatus.SENDPHARMERROR);
            presPrescriptionService.updateById(presPrescription);
            logErrorService.presBackLog("请求参数数据加密失败", "处方发送到一方制药药房异常", "bodyDTO=" + JSON.toJSONString(bodyDTO));
            return succ;
        }
        log.info("bodyDTO:{}", bodyDTO);
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("Content-Type", "application/json");
        httpHeaders.add("target-data-source", getTargetDataSource());
        httpHeaders.add("xmtoken", getToken());
        HttpEntity<String> entity = new HttpEntity<>(JSON.toJSONString(bodyDTO), httpHeaders);
        log.info("请求数据:{}", entity);
        ResponseEntity<String> res;
        try {
            res = restTemplate.postForEntity(pharmacyDocking.getServicesUrl(), entity, String.class);
        } catch (RestClientException e) {
            e.printStackTrace();
            logErrorService.presBackLog("药房下单接口请求错误", "处方发送到一方制药药房异常", "message=" + e.getMessage());
            return succ;
        }
        log.info("result:{}", res.getBody());
        JSONObject jsonObj = JSON.parseObject(res.getBody());
        if (jsonObj == null) {
            logErrorService.presBackLog("药房下单接口无数据返回", "处方发送到一方制药药房异常", "res=" + res);
            return succ;
        }
        if (jsonObj.getInteger("code") != 200) {
            logErrorService.presBackLog("药房下单接口返回异常信息", "处方发送到一方制药药房异常", "res=" + res);
            return succ;
        }
        ReturnPresBodyResultDTO resultDTO;
        try {
            resultDTO = JSON.parseObject(jsonObj.getString("data"), ReturnPresBodyResultDTO.class);
        } catch (Exception e) {
            presPrescription.setStatus(PresConstants.PresStatus.SENDPHARMERROR);
            presPrescriptionService.updateById(presPrescription);
            logErrorService.presBackLog("发送处方到药房成功, 解析返回数据错误", "处方发送到一方制药药房异常", "jsonBody=" + presPrescription);
            return succ;
        }
        PresPrescription update1 = new PresPrescription();
        update1.setTencode(pay.getServerNo());
        update1.setStatus(PresConstants.PresStatus.SENDPHARM);
        update1.setUpdateDate(LocalDateTime.now());
        boolean flag = presPrescriptionService.updateById(update1);
        if (!flag) {
            presPrescription.setStatus(PresConstants.PresStatus.SENDPHARMERROR);
            presPrescriptionService.updateById(presPrescription);
            logErrorService.presBackLog("发送处方到药房成功, 处方更新失败", "处方发送到一方制药药房异常", "jsonBody=" + presPrescription);
            return succ;
        }
        PresYfDetail update2 = new PresYfDetail();
        update2.setTencode(pay.getServerNo());
        update2.setThirdPartyId(pay.getOrderNo());
        update2.setOrderNo(resultDTO.getOrderNo());
        flag = presYfDetailService.updateById(update2);
        if (!flag) {
            presPrescription.setStatus(PresConstants.PresStatus.SENDPHARMERROR);
            presPrescriptionService.updateById(presPrescription);
            logErrorService.presBackLog("发送处方到药房成功, 一方制药处方详情更新失败", "处方发送到一方制药药房异常", "jsonBody=" + presPrescription);
            return succ;
        }
        succ = true;
        return succ;
    }

    @Override
    public void cancelPres(CancelPresReq req) {
        PresPrescription presPrescription = presPrescriptionService.getById(req.getTencode());
        if (presPrescription == null) {
            throw new ZekeException(ZkExceptionEnum.CANCEL_PRES_ERROR, "查询处方失败");
        }
        Pharmacy pharmacy = pharmacyService.getById(presPrescription.getPharmId());
        if (pharmacy == null) {
            throw new ZekeException(ZkExceptionEnum.CANCEL_PRES_ERROR, "查询药房失败");
        }
        QueryWrapper<PharmacyDocking> qd = new QueryWrapper<>();
        qd.lambda().eq(PharmacyDocking::getPharId, pharmacy.getId()).eq(PharmacyDocking::getStatus, PharConstants.DockingStatus.NOMER);
        PharmacyDocking pharmacyDocking = pharmacyDockingService.getOne(qd);
        if (pharmacyDocking == null) {
            throw new ZekeException(ZkExceptionEnum.CANCEL_PRES_ERROR, "查询药房信息失败");
        }
        QueryWrapper<PresYfDetail> qw = new QueryWrapper<>();
        qw.lambda().eq(PresYfDetail::getTencode, req.getTencode());
        qw.lambda().select(PresYfDetail::getThirdPartyId);
        PresYfDetail yfDetail = presYfDetailService.getOne(qw);
        if (yfDetail == null) {
            throw new ZekeException(ZkExceptionEnum.CANCEL_PRES_ERROR, "查询一方制药信息为空");
        }
        SendCancelPresDTO dto = new SendCancelPresDTO();
        dto.setThirdPartyId(yfDetail.getThirdPartyId());
        String json = JSON.toJSONString(dto);
        try {
            dto.setEncryptedContent(AESUtil.encrypt(json, pharmacyDocking.getSecretKey()));
        } catch (Exception e) {
            throw new ZekeException(ZkExceptionEnum.CANCEL_PRES_ERROR, "加密数据错误");
        }
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("Content-Type", "application/json");
        httpHeaders.add("target-data-source", getTargetDataSource());
        httpHeaders.add("xmtoken", getToken());
        HttpEntity<String> entity = new HttpEntity<>(JSON.toJSONString(dto), httpHeaders);
        log.info("请求数据:{}", entity);
        ResponseEntity<String> res;
        try {
            res = restTemplate.postForEntity(pharmacyDocking.getCancelUrl(), entity, String.class);
        } catch (RestClientException e) {
            e.printStackTrace();
            throw new ZekeException(ZkExceptionEnum.CANCEL_PRES_ERROR, "请求错误");
        }
        log.info("result:{}", res.getBody());
        JSONObject jsonObj = JSON.parseObject(res.getBody());
        if (jsonObj == null) {
            throw new ZekeException(ZkExceptionEnum.CANCEL_PRES_ERROR, "返回数据转换异常");
        }
        if (jsonObj.getInteger("code") != 200) {
            throw new ZekeException(ZkExceptionEnum.CANCEL_PRES_ERROR, jsonObj.getString("msg"));
        }
        PresPrescription update = new PresPrescription();
        update.setTencode(req.getTencode());
        update.setStatus(PresConstants.PresStatus.CANCEL);
        update.setUpdateDate(LocalDateTime.now());
        boolean flag = presPrescriptionService.updateById(update);
        if (!flag) {
            logErrorService.presBackLog("取消处方一方制药返回成功,数据修改失败", "取消处方", "tencode=" + presPrescription.getTencode());
            throw new ZekeException(ZkExceptionEnum.CANCEL_PRES_ERROR, "数据修改失败,请联系管理员");
        }
    }

    @Override
    public Object presCallback(CallbackPresStatusReq req) {
        return null;
    }

    @Override
    public Object expressCallback(CommonParamReq req) {
        return null;
    }

    @Override
    public void updatePresPatientAddrInfo(PresPatientAddrReq req) {
        UpdateWrapper<PresYfDetail> uw = new UpdateWrapper<>();
        uw.lambda().eq(PresYfDetail::getTencode, req.getTencode());
        uw.lambda().set(PresYfDetail::getBorrowerName, req.getReceiver());
        uw.lambda().set(PresYfDetail::getBorrowerPhone, req.getMobileNumber());
        uw.lambda().set(PresYfDetail::getBorrowerCity, req.getProvince() + "," + req.getCity() + "," + req.getDistrict());
        uw.lambda().set(PresYfDetail::getBorrowerAddress, req.getAddr());
        boolean flag = presYfDetailService.update(uw);
        if (!flag) {
            throw new ZekeException(400, "修改处方收货人信息失败");
        }
    }
}
